<?php
/**
 * Miffos framework
 * ----------------------------------------------
 *
 * Copyright (c) 2008, 2009 Martin Sadový (http://sodae.cz)
 *
 * This source file is subject to the "Miffos license" that is bundled
 * with this package in the file license.txt.
 *
 * @copyright  Copyright (c) 2008, 2009 Martin Sadový
 * @license    license.txt
 * @link       http://miffos.sodae.cz
 * @package    miffos
 * @version    $Id$
 */

class View{

    protected $isTemplate = false;

    private $controller;

    private $variable = array();

    private $helpers = array();

    private $service = null;

    private $filter;

    private $show = true;

    public function __construct(&$controller)
    {
        $this->controller = $controller;
        $this->loadHelper('html');
        $this->setFilter('html');
    }



    public function setShow($show){
        $this->show = $show;
    }


    /**
     * Return controller instance
     * @return string
     */
    public function getController()
    {
        return $this->controller;
    }



    /**
     * Load Helper (in View ${name helper} )
     * @param string $name
     */
    public function loadHelper($name)
    {
        $file = dirname(__FILE__).'/View/Helpers/'.$name.'.php';
        if(file_exists($file)){
           require_once($file);
           $nameClass = $name.'Helper';
           $this->helpers[$name] = new $nameClass;
        }

    }


    /**
     * Return service instance
     * @param string $name
     */
    public function service($name = null)
    {
        require_once dirname(__FILE__).'/View/Service.php';
        
        if(!is_null($name)){
           $file = dirname(__FILE__).'/View/Service/'.$name.'.php';
            if(file_exists($file)){
                require_once $file;
                $class = $name.'ViewService';
                $this->service = new $class($this);
            }else{
                throw new ApplicationException('missing-view-service:'.$name,6);
            }
        }
        return $this->service;
    }



    /**
     * Set Filter for view output
     * @param string $name
     */
    public function setFilter($name)
    {
        require_once dirname(__FILE__).'/View/Filter.php';
        
        if(!is_null($name)){
           $this->filter = new ViewFilter($name);
        }
        return $this->filter;
    }



    /**
     * Return all possible name view file
     * @param string $name
     * @return array
     */
    private function getViewFile($name)
    {
        if(empty($name)) $name = $this->controller->param('action');

        $array = array(Sorter::getViewFile($this->controller->param('namespace').'/'.$this->controller->param('controller').'/'.$name.'.action'),
                       Sorter::getViewFile($this->controller->param('controller').'/'.$name.'.action'),
                       Sorter::getViewFile($this->controller->param('namespace').'/'.$this->controller->param('controller').'/'.$name),
                       Sorter::getViewFile($this->controller->param('controller').'/'.$name),
                       Sorter::getViewFile($this->controller->param('namespace').'/'.$name.'.action'),
                       Sorter::getViewFile($name.'.action'),
                       Sorter::getViewFile($name)
                       );

        return $array;
    }



    /**
     * Return all possible name view file
     * @param string $name
     * @return array
     */
    private function getTemplateFile()
    {

        $array = array(Sorter::getViewFile($this->controller->param('namespace').'/'.$this->controller->param('controller').'/@layout'),
                       Sorter::getViewFile($this->controller->param('controller').'/@layout'),
                       Sorter::getViewFile($this->controller->param('namespace').'/@layout'),
                       Sorter::getViewFile('@layout')
                       );

        return $array;
    }


    /**
     * Render View
     * @param string $name
     * @return string
     */
    public function render($name = null)
    {
        if(!$this->show) return '';
        if(is_null($this->service)){
            $array = $this->isTemplate?$this->getTemplateFile():$this->getViewFile($name);
            foreach($array as $file){
                if(file_exists(Application::$appDir.$file)){
                   return $this->_renderView(Application::$appDir.$file);
                }
            }
        }else{
            return $this->service()->render();
        }

        throw new ApplicationException( 'missing-'.($this->isTemplate?'layout-layout':'view-'.$name) );
    }



    /**
     * Return content render file
     * @return string
     */
    private function _renderView($__file__){

        ob_start();
        extract($this->variable);
        extract($this->helpers);
        if(is_null($__file__)){
            echo $this->service()->render();
        }else{
           require $__file__;
        }
        $return = ob_get_contents();
        ob_end_clean();
        return $this->filter->render($return);
    }



    public function snippet($name,$ext='phtml')
    {
        $file = Application::$appDir.Sorter::getViewDir().$name.'.'.$ext;
        if(file_exists($file)){
            return $this->_renderView($file);
        }else
            throw new ApplicationException('missing-view:'.$file,3);
    }

    /**
     * Magic function , set varible
     */
    public function __get($name)
    {
        return $this->variable[$name];
    }

    public function __set($name,$value)
    {
        $this->variable[$name] = $value;
    }

    public function __isset($name)
    {
        return isset($this->variable[$name]);
    }

    public function __unset($name)
    {
        unset($this->variable[$name]);
    }

}


/**
 * Class Template
 */
class Template extends View{

    public $isTemplate = true;

    /**
     * Set variable $content in templates
     * @param string $data
     */
    public function setContent($data){
        parent::__set('content', $data);
    }

}
?>